package router

import (
	"bytes"
	"encoding/json"
	"gitee.com/baizhige/go-server-tempalte/common/auth"
	"gitee.com/baizhige/go-server-tempalte/common/client"
	"gitee.com/baizhige/go-server-tempalte/common/config"
	"gitee.com/baizhige/go-server-tempalte/common/constant"
	"gitee.com/baizhige/go-server-tempalte/common/log"
	"gitee.com/baizhige/go-server-tempalte/util/goroutine"
	"gitee.com/baizhige/go-server-tempalte/util/mask"
	"gitee.com/baizhige/mongong-go"
	"github.com/gin-gonic/gin"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"io"
	"time"
)

// reqPreLog 请求前置日志
func reqPreLog[T auth.User](c *gin.Context, router *Router, traceID string) (err error) {

	now := time.Now()
	logObj := &RequestLog{
		Id:      primitive.NewObjectID(),
		TraceId: traceID,
		Node:    config.Project.Node,
		Project: config.Project.Name,
		ReqTime: &now,
	}
	//客户端相关信息
	logObj.ClientId, _ = client.GetId(traceID, c)
	logObj.ClientIp = client.GetIP(traceID, c)

	//用户相关信息
	user, err := auth.GetUser[T](traceID, c)
	if err == nil {
		logObj.Uid = user.IdString()
	}

	//请求相关信息
	logObj.Method = c.Request.Method
	logObj.Url = c.Request.URL.Path
	reqMsg := &HttpMessageInfo{Header: c.Request.Header}
	all, err := io.ReadAll(c.Request.Body)
	if err == nil {
		reqMsg.Payload = mask.Json(string(all), router.LogConfig.ReqMask...)
	}
	c.Request.Body = io.NopCloser(bytes.NewReader(all))
	logObj.ReqInfo = reqMsg

	c.Set(constant.ContextLog, logObj)

	//打印日志
	if router.LogConfig.ReqPrint {
		log.InfoTF(traceID, "reqPreLog request info : %s", logObj.ToString())
	}

	return
}

func respLog(traceId string, router *Router, c *gin.Context) error {

	res, _, err := GetResponseEntity(traceId, c)
	if err != nil {
		return err
	}
	if res != nil {
		return recordLog(traceId, router, c, res)
	}

	return nil
}

func recordLog(traceId string, router *Router, c *gin.Context, resp any) error {
	value, _ := c.Get(constant.ContextLog) //只要从中间件进来 一定存在

	logObj := value.(*RequestLog)
	respInfo := &HttpMessageInfo{Header: c.Writer.Header()}

	if resp != nil {
		marshal, _ := json.Marshal(resp)
		respInfo.Payload = string(marshal)
	}
	now := time.Now()
	logObj.RespTime = &now
	logObj.RespInfo = respInfo

	//打印日志
	if router.LogConfig.ResPrint {
		log.InfoTF(traceId, "respLog request complete : %s", logObj.ToString())
	}

	//日志异步入库
	if router.LogConfig.InDb {
		goroutine.Safe(func() {
			_, err := mongong.Coll[RequestLog]().InsertOne(logObj)
			if err != nil {
				log.ErrorTF(traceId, "respLog insert fail :%v", err)
			}
		})
	}
	return nil
}
